const NodeSSH = require('node-ssh')
const { validate } = require('schema-utils')
const { green } = require('colorette')
const schemaRules = require('./scahema')
const { isLocal, cliLoading } = require('./utils')
const loading = cliLoading()

class AutoSsh {
	constructor(options) {
		//如果不是在本地运行就不触发
		if (!isLocal()) return
		this.nodessh = new NodeSSH()
		this.options = options
	}

	apply (compiler) {
		if (!isLocal()) return
		compiler.hooks.afterEmit.tapAsync('autossh', async (compilation, callback) => {
			try {
				const options = this.options
				//校验options
				validate(schemaRules, this.options, {
					name: 'autoSsh',
					baseDataPath: 'options',
					postFormatter: (formattedError, error) => {
						// 做一些处理
						return formattedError
					},
				})
				//连接服务器
				if (options.host) {
					await this.connect()
				}
				//上传文件
				if (options.host && options.remotePath) {
					await this.uploadFiles(compilation.outputOptions.path, remotePath)
				}
				this.nodessh.dispose()
				callback()
			} catch (e) {
				callback()
			}
		})
	}

	//连接服务器
	async connect () {
		try {
			console.log(`${green('\n正在连接服务器')}`)
			const options = this.options
			const config = {
				host: options.host,
				username: options.username,
				password: options.password
			}
			await this.nodessh.connect(config)
			loading.stop('连接服务器成功')
		} catch (e) {
			loading.stopError('连接服务器失败')
			throw e
		}
	}

	//上传文件
	async uploadFiles (outPath, remotePath) {
		try {
			console.log(`${green('\n正在上传文件')}`)
			this.nodessh.execCommand(`rm -rf ${remotePath}/*`)
			const status = await this.nodessh.putDirectory(outPath, remotePath, {
				//递归
				recursive: true,
				//并发上传
				concurrency: 10
			})
			if (status) {
				loading.stop('上传文件成功')
			} else {
				throw '上传文件失败'
			}
		} catch (e) {
			loading.stopError('上传文件失败')
			throw e
		}
	}
}

module.exports = AutoSsh 